package model;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public class Main {
	public static int BOARD_SIZE = 8;
	public static int GENERATION_SIZE = 10; // THIS MUST BE AN EVEN INTEGER OKAY?
	public static int BREED_FUNC = 0;
	/**
	 * Tests all three breed functions individually.
	 */
	public static void testBreeds() {
		Scanner scn = new Scanner(System.in);
		System.out.print("Test iterations: ");
		int iters = scn.nextInt();
		System.out.print("Goal: ");
		int goal = scn.nextInt();
		System.out.print("Max Generations: ");
		int max = scn.nextInt();
		//OK NOW RUN TESTS
		for(int i=0;i<iters;i++){
			//BREED_FUNC = 0;
			//runEvolve(goal,max);
			BREED_FUNC = 1;
			Pattern a = null;
			System.out.println((a=runEvolve(goal,max)));
			BREED_FUNC = 2;
			System.out.println(runEvolve(goal,max));
		}
		
	}
	/**
	 * Runs the evolution sim with a goal value and cutoff.
	 * @param goal Obvoius
	 * @param cutoff Obvious
	 * @return The best result we found
	 */
	public static Pattern runEvolve(int goal,int cutoff) {
		Pattern[] currGen = getFirstGeneration();
		int generationCount = 0;
		do{
			Pattern[] children = breedGeneration(currGen);
			Pattern[] midGen = new Pattern[GENERATION_SIZE * 2];
			System.arraycopy(currGen, 0, midGen, 0, GENERATION_SIZE);
			System.arraycopy(children, 0, midGen, GENERATION_SIZE, GENERATION_SIZE);
			Arrays.sort(midGen);
			midGen = Arrays.copyOf(midGen, GENERATION_SIZE);
			
			//NO MUTATIONS YET, WHY DON'T YOU GO FOR IT
			
			currGen = midGen;
			generationCount++;
		}while(currGen[0].getScore() > goal && generationCount < cutoff);
		if(generationCount >= cutoff) {
			System.out.println("No solution found in ........ " + generationCount + " generations. Alg. [" + BREED_FUNC + "]");
			return null;
		}
		else {
			System.out.println(currGen[0].toString() + " ... in " + generationCount + " generations. Alg. [" + BREED_FUNC + "]");
			return currGen[0];
		}
	}
	/**
	 * Interbreeds the passed generation of patterns.
	 * Every 2 parents generates 2 children.
	 * @param currGen A generation of n Patterns
	 * @return An array of n Patterns
	 */
	public static Pattern[] breedGeneration(Pattern[] currGen) {
		Pattern[] children = new Pattern[GENERATION_SIZE];
		for(int i=0;i<children.length/2;i++){
			Pattern m1 = currGen[i*2];
			Pattern m2 = currGen[i*2 +1];
			Pattern[] temp = m1.breedWith(m2, 2);
			System.arraycopy(temp, 0, children, i*2, 2);
		}
		return children;
	}
	/**
	 * Randomly creates the first generation.
	 * @return Random genrations
	 */
	public static Pattern[] getFirstGeneration(){
		Pattern[] ret = new Pattern[GENERATION_SIZE];
		for(int i=0;i<ret.length;i++)
			ret[i] = new Pattern(getPermutation());
		return ret;
	}
	/**
	 * Permutation fucntion sthidngidgya
	 * @return
	 */
	public static int[] getPermutation() {
		int[] ret = new int[BOARD_SIZE];
		List<Integer> used = new ArrayList<Integer>(ret.length);
		Random r = new Random();
		for(int i=0;i<ret.length;i++){
			int ri = r.nextInt(ret.length);
			while (used.contains(ri))
				ri = r.nextInt(ret.length);
			used.add(ri);
			ret[ri] = i;
		}
		return ret;
	}
	/**
	 * THE MAIN FUNCTION WHAT COULD THIS DO
	 * @param args
	 */
	public static void main(String[] args){
		testBreeds();
		System.exit(0);
		int[] a = {0,1,2,3,4,5,6,7};
		Pattern p = new Pattern(a);
		System.out.println(p);
	}
}
